﻿using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
using Domain;
using FrameworkCore.Helpers;
using FrameworkCore.Interfaces;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System;
using System.Globalization;
using System.Text.RegularExpressions;

namespace AiBLSmartEdu.Module.CreditAnalysis.API.Services
{
    public class CreditAnalysisBackgroundService: BackgroundService
    {
        private readonly TimeSpan _interval = TimeSpan.FromSeconds(1);

        private readonly ILogger<CreditAnalysisBackgroundService> _logger;
        private readonly IOcrService _ocrService;
        private readonly PdfHelper _pdfHelper;
        private readonly DocumentServices _documentServices;
        private readonly IWebHostEnvironment _env;

        public CreditAnalysisBackgroundService(
            DocumentServices documentServices,
            ILogger<CreditAnalysisBackgroundService> logger,
            IOcrService ocrService,
            PdfHelper pdfHelper,
            IWebHostEnvironment env)
        {
            _documentServices = documentServices;
            _logger = logger;
            _ocrService = ocrService;
            _pdfHelper = pdfHelper;
            _env = env;
        }

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            // 获取wwwroot的物理路径
            string wwwrootPath = _env.WebRootPath;
            string tempOutputDirectory = string.Empty;

            while (!stoppingToken.IsCancellationRequested)
            {
                var needAnalysisDocuments = await _documentServices.QueryAsync(q => q.Where(x => x.Status == JobStatus.NotStart));
                if (needAnalysisDocuments == null || needAnalysisDocuments.Count == 0) 
                {
                    await Task.Delay(TimeSpan.FromSeconds(10), stoppingToken);
                    continue;
                }

                foreach (var document in needAnalysisDocuments) 
                {
                    var id = document.Id;
                    var text = string.Empty;

                    try
                    {
                        await _documentServices.UpdatStatusAsync(id, JobStatus.Pending);
                        var normalizedPath = document.Path.TrimStart(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
                        var filePath = Path.Combine(wwwrootPath, normalizedPath);
                        if (string.IsNullOrWhiteSpace(filePath))
                        {
                            continue;
                        }

                        _logger.LogInformation("开始解析");

                        await _documentServices.UpdatStatusAsync(id, JobStatus.Doing);

                        if (filePath.EndsWith(".png"))
                        {
                            text = await _ocrService.PerformOcrAsync(filePath);
                        }
                        else if (filePath.EndsWith(".pdf"))
                        {
                            string tempDirectoryName = Guid.NewGuid().ToString();
                            tempOutputDirectory = Path.Combine(Path.GetDirectoryName(filePath)!, tempDirectoryName);

                            var psfs = _pdfHelper.SplitPdfIntoSinglePages(filePath, tempOutputDirectory);

                            foreach (var page in psfs)
                            {
                                _pdfHelper.ConvertPdfToDocxFormat(Path.Combine(tempOutputDirectory, page), tempOutputDirectory, page.Replace("pdf", "docx"));
                            }

                            string[] docxFiles = Directory.GetFiles(tempOutputDirectory, "*.docx");

                            foreach (var docxFile in docxFiles)
                            {
                                text += ExtractTextFromDocx(docxFile);
                            }
                        }

                        await ExtractAndSumCreditInfoAsnyc(id, text);
                        await ExtractAndSumLoanInfoAsnyc(id, text);

                        await _documentServices.UpdatStatusAsync(id, JobStatus.Completed);
                    }
                    catch (Exception ex)
                    {
                        await _documentServices.UpdatStatusAsync(id, JobStatus.NotStart);
                        _logger.LogError($"解析失败：{ex.Message}");
                        await Task.Delay(TimeSpan.FromMinutes(1), stoppingToken);
                    }
                    finally
                    {
                        if (Directory.Exists(tempOutputDirectory))
                        {
                          //  Directory.Delete(tempOutputDirectory, recursive: true);
                        }
                    }

                }

                await Task.Delay(_interval, stoppingToken);
            }
        }

        /// <summary>
        /// 提取Word文档内容
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        private static string ExtractTextFromDocx(string filePath)
        {
            var text = string.Empty;
            using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(filePath, false))
            {
                Body body = wordDoc.MainDocumentPart!.Document.Body!;
                foreach (var para in body.Elements<Paragraph>())
                {
                    text += para.InnerText;
                }

                return text.Replace(" ", "");
            }
        }

        /// <summary>
        /// 提取和汇总信用卡信息
        /// </summary>
        /// <param name="id"></param>
        /// <param name="text">文本</param>
        private async Task ExtractAndSumCreditInfoAsnyc(long id, string text)
        {
            // 定义正则表达式模式
            // string pattern = @"信用额度([0-9,]+)，已使用额度([0-9,]+)";
            string pattern = @"([\u4e00-\u9fa5]+银行股份有限公司[\u4e00-\u9fa5]*)(?:.*?信用额度([0-9,]+)，已使用额度([0-9,]+))";

            // 创建正则表达式对象
            Regex regex = new Regex(pattern, RegexOptions.Singleline);

            // 查找匹配的内容
            MatchCollection matches = regex.Matches(text);

            string summary = $@"
       信用卡

";
            decimal totalCreditLimit = 0;
            decimal totalUsedAmount = 0;


            // 遍历所有匹配项并处理
            foreach (Match match in matches)
            {
                // 提取信用额度和已使用额度
                string bankName = match.Groups[1].Value.Replace("日", "");
                string creditLimitStr = match.Groups[2].Value;
                string usedAmountStr = match.Groups[3].Value;

                // 去除千位分隔符并转换为数字
                decimal creditLimit = decimal.Parse(creditLimitStr, NumberStyles.AllowThousands, CultureInfo.InvariantCulture);
                decimal usedAmount = decimal.Parse(usedAmountStr, NumberStyles.AllowThousands, CultureInfo.InvariantCulture);

                summary += @$"

银  行  名 称：{bankName}
信  用  额 度：{creditLimit}
已 使用 额 度：{usedAmountStr}
";

                // 累加
                totalCreditLimit += creditLimit;
                totalUsedAmount += usedAmount;
            }

            summary += @$"

            总计
信 用总额 度：{totalCreditLimit}
已使用总额度：{totalUsedAmount}
";
            await _documentServices.UpdatContentSummaryAsync(id, text, summary);

        }

        /// <summary>
        /// 提取和汇总贷款信息
        /// </summary>
        ///  <param name="id"></param>
        /// <param name="text">文本</param>
        /// <returns></returns>
        private async Task ExtractAndSumLoanInfoAsnyc(long id, string text)
        {
            // 定义正则表达式模式
            List<string> patterns=new List<string>() 
            {
                 @"(\d{4}年\d{2}月\d{2}日)([^发放]+)发放的(?<loan>\d{1,3}(?:,\d{3})*)元.*?余额(?:为)?(?<balance>\d{1,3}(?:,\d{3})*)",
                 @"(\d{4}年\d{2}月\d{2}日)([^0-9]+?)为其他个人消费贷款授信，额度有效期至\d{4}年\d{2}月\d{2}日.*?信用额度(?<loan>\d{1,3}(?:,\d{3})*)元.*?余额(?:为)?(?<balance>\d{1,3}(?:,\d{3})*)"
            };

            string summary = (await _documentServices.GetByIdAsync(id))?.Summary ?? string.Empty;

            summary += $@"
       贷  款

";
            decimal totalLoanAmount = 0;
            decimal totalBalanceAmount = 0;

            foreach (var pattern in patterns) 
            {
                // 创建正则表达式对象
                Regex regex = new Regex(pattern, RegexOptions.Singleline);

                // 查找匹配的内容
                MatchCollection matches = regex.Matches(text);

                // 遍历所有匹配项并处理
                foreach (Match match in matches)
                {
                    // 提取信用额度和已使用额度
                    string bankName = match.Groups[2].Value.Trim();
                    string loanAmountStr = match.Groups["loan"].Value;
                    string balanceAmountStr = match.Groups["balance"].Value;

                    // 去除千位分隔符并转换为数字
                    decimal loanAmount = decimal.Parse(loanAmountStr, NumberStyles.AllowThousands, CultureInfo.InvariantCulture);
                    decimal balanceAmount = decimal.Parse(balanceAmountStr, NumberStyles.AllowThousands, CultureInfo.InvariantCulture);

                    summary += @$"

银  行  名 称：{bankName}
贷  款  金 额：{loanAmount}
余         额：{balanceAmount}

";
                    // 累加
                    totalLoanAmount += loanAmount;
                    totalBalanceAmount += balanceAmount;
                }
            }

            summary += @$"

            总计
贷  款 总 金 额：{totalLoanAmount}
总     余    额：{totalBalanceAmount}

";
            await _documentServices.UpdatContentSummaryAsync(id, text, summary);
        }
    }
}
